{# this template is used to generate a nginx.conf for booting a nginx server based on the given environment inventory #}

worker_processes {{ nginx.wpn.router }};
worker_rlimit_nofile 4096;

events {
{# default: 1024 #}
    worker_connections 4096;
}

http {
{# allow large uploads, need to thread proper limit into here #}
    client_max_body_size 50M;

    rewrite_log on;
{# change log format to display the upstream information #}
    log_format combined-upstream '$remote_addr - $remote_user [$time_local] '
        '[#tid_$request_id] $request $status $body_bytes_sent '
        '$http_referer $http_user_agent $upstream_addr';
    access_log /logs/nginx_access.log combined-upstream;

{# needed to enable keepalive to upstream controllers #}
    proxy_http_version 1.1;
    proxy_set_header Connection "";
    proxy_buffers 16 4k;

{% if controller.protocol == 'https' %}
    proxy_ssl_session_reuse on;
    proxy_ssl_name {{ controller.ssl.cn }};
    proxy_ssl_verify on;
    proxy_ssl_trusted_certificate /etc/nginx/{{ controller.ssl.cert }};
    proxy_ssl_protocols TLSv1.1 TLSv1.2;
    proxy_ssl_certificate /etc/nginx/{{ controller.ssl.cert }};
    proxy_ssl_certificate_key /etc/nginx/{{ controller.ssl.key }};
{% endif %}

    gzip_static on;
    types {
        text/html                                        html htm shtml;
        text/css                                         css;
        text/xml                                         xml;
        image/gif                                        gif;
        image/jpeg                                       jpeg jpg;
        image/png                                        png;
        image/svg+xml                                    svg svgz;
        image/x-icon                                     ico;
        image/x-jng                                      jng;
        image/x-ms-bmp                                   bmp;
        application/javascript                           js;
        application/json                                 json;
        application/java-archive                         jar war ear;
        application/pdf                                  pdf;
    }

    upstream controllers {
        # Mark the controller as unavailable after fail_timeout seconds, to not get any requests during restart.
        # Otherwise, nginx would dispatch requests when the container is up, but the backend in the container not.
        # From the docs:
        #  "normally, requests with a non-idempotent method (POST, LOCK, PATCH) are not passed to
        #   the next server if a request has been sent to an upstream server"
{% for c in groups['controllers'] %}
        server {{ hostvars[c].ansible_host }}:{{ controller.basePort + groups['controllers'].index(c) }} fail_timeout=60s;
{% endfor %}
        keepalive 512;
    }

{# determine "special users" to send the header accordingly #}
    map "$remote_user" $special_user {
      default not_special;
{% for user in nginx.special_users %}
      "{{ user }}" special;
{% endfor %}
    }

    map "$special_user:$http_x_ow_extra_logging" $extra_logging {
      default "off";
      "special:off" off;
      "special:on" on;
      "special:" on;
    }

    proxy_set_header X-OW-EXTRA-LOGGING $extra_logging;
    # Set the request id generated by nginx as tid-header to the upstream.
    # This tid is either the request-id generated by ngix or a tid, sent by the caller.
    proxy_set_header {{ transactions.header }} $request_id;

    # Send the tid always back as header.
    add_header {{ transactions.header }} $request_id always;

{# Turn off sending information about the server to the client #}
    server_tokens off;

    # Redirect all http to https.
    server {
        listen 80 default_server;
        server_name _;
        return 308 https://$host$request_uri;
    }

    server {
        listen 443 default ssl;

        # Match namespace, note while OpenWhisk allows a richer character set for a
        # namespace, not all those characters are permitted in the (sub)domain name.
        # If namespace does not match, no vanity URL rewriting takes place.
        server_name ~^(?<namespace>[0-9a-zA-Z-]+)\.{{ whisk_api_localhost_name | default(whisk_api_host_name) | default(whisk_api_localhost_name_default) }}$;

        # Recommended TLS settings from: https://wiki.mozilla.org/Security/Server_Side_TLS
        ssl_session_cache    shared:SSL:1m;
        ssl_session_timeout  10m;
        ssl_certificate      /etc/nginx/{{ nginx.ssl.cert }};
        ssl_certificate_key  /etc/nginx/{{ nginx.ssl.key }};
        {% if nginx.ssl.password_file %}
        ssl_password_file   "/etc/nginx/{{ nginx.ssl.password_file }}";
        {% endif %}
        ssl_client_certificate /etc/nginx/{{ nginx.ssl.client_ca_cert }};
        ssl_verify_client {{ nginx.ssl.verify_client }};
        ssl_protocols        TLSv1.2;
        ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256;
        ssl_prefer_server_ciphers on;
        proxy_ssl_session_reuse on;

        # proxy to the web action path
        location / {
            if ($namespace) {
              rewrite    /(.*) /api/v1/web/${namespace}/$1 break;
            }
            proxy_pass {{ controller.protocol }}://controllers;
            proxy_read_timeout 75s; # 70+5 additional seconds to allow controller to terminate request
        }

        # proxy to 'public/html' web action by convention
        location = / {
            if ($namespace) {
              rewrite    ^ /api/v1/web/${namespace}/public/index.html break;
            }
            proxy_pass {{ controller.protocol }}://controllers;
            proxy_read_timeout 75s; # 70+5 additional seconds to allow controller to terminate request
        }

        location /blackbox.tar.gz {
            return 301 https://github.com/apache/openwhisk-runtime-docker/releases/download/sdk%400.1.0/blackbox-0.1.0.tar.gz;
        }

        location /cli {
            autoindex on;
            alias /etc/nginx/cli/go/download;
        }

        # this is here for backward compatibility
        location /cli/go/download {
            rewrite /cli/go/download(.*) /cli$1 permanent;
        }

        location /metrics {
            deny all;
        }

{% if nginx.htmldir %}
        location /ui {
            alias /usr/share/nginx/html;
        }
{% endif %}
    }
}
